#ifndef LHC_UNICODE_STRING_H_INCLUDED_
#define LHC_UNICODE_STRING_H_INCLUDED_

#include "Utf16CodeUnit.h"
#include "CultureInfo.h"
#include "utilities.h"
#include "ByteArray.h"
#include "Utf16Array.h"
#include <vector>
#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <QtCore/qstring.h>


namespace lhcutils
{

namespace encodings
{
	const char * Utf8 = "utf8";
	const char * Utf16 = "utf16";
	const char * Utf32 = "utf32";
	const char * Ascii = "ascii";
}

struct StringComparison
{
	enum Value
	{
		Ordinal,
		OrdinalIgnoreCase,
		CurrentCulture,
		CurrentCultureIgnoreCase
	};
};

struct CaseType
{
	enum Value
	{
		Sensitive,
		IgnoreCase
	};
};
	
class UnicodeString
{
private:
	QString m_qstr;
public:
	UnicodeString(const char* cString);
	UnicodeString(const void* sourceString, const char* sourceEncodingName);
	UnicodeString(const void* sourceString, size_t numBytesInSource, const char* sourceEncodingName);
	UnicodeString(double num, const CultureInfo& culture);
	//UnicodeString(double num, const char* format, const CultureInfo& culture); // Not needed now, would require either coupling the format string to the library used or making our own format and translating it to the library's format
	//UnicodeString(const UnicodeString& other); // compiler-generated is ok

private:
	QString InitQString(const void* sourceString, const char* sourceEncodingName);
	QString InitQString(const void* sourceString, size_t numBytesInSource, const char* sourceEncodingName);
	QString InitQString(double num, const CultureInfo& culture);

public:

	//UnicodeString& operator=(const UnicodeString& other); // compiler-generated is ok

	ByteArray ToEncoding(const char* encodingName) const;
	ByteArray ToNullTerminatedEncoding(const char* encodingName) const;

	ByteArray ToUtf8() const;
	ByteArray ToUtf8NullTerminated() const;

	Utf16Array ToUtf16() const;
	Utf16Array ToUtf16NullTerminated() const;

	ByteArray ToAscii() const;
	ByteArray ToAsciiNullTerminated() const;

	// XXX: StartsWith does not actually take culture into account.
	bool StartsWith(const UnicodeString& str, StringComparison::Value comparison = StringComparison::CurrentCulture) const;
	bool StartsWith(const UnicodeString& str, CaseType::Value caseBehavior, const CultureInfo& culture) const;

	// XXX: EndsWith does not actually take culture into account.
	bool EndsWith(const UnicodeString& str, StringComparison::Value comparison = StringComparison::CurrentCulture) const;
	bool EndsWith(const UnicodeString& str, CaseType::Value caseBehavior, const CultureInfo& culture) const;

	// Returns the number of 16-bit *code units* in the string. This may be different from the number of glyphs it displays.
	// See http://mathias.gaunard.com/unicode/doc/html/unicode/introduction_to_unicode.html
	uint32_t GetCodeUnitLength() const;

	Utf16CodeUnit GetCodeUnitAt(uint32_t index) const;
	
	static bool EncodingSupported(const char* encodingName);
};

typedef boost::shared_ptr<UnicodeString> StringPtr;

StringPtr ustr(const char* cString);
StringPtr ustr(const void* sourceString, const char* sourceEncodingName);
StringPtr ustr(const void* sourceString, size_t numBytesInSource, const char* sourceEncodingName);
#ifdef _WIN32
StringPtr winstr(const wchar_t* utf16SourceWithNullChar);
StringPtr winstr(const wchar_t* utf16Source, size_t numCharsInSource);
#endif

const UnicodeString operator+(const UnicodeString& lhs, const UnicodeString& rhs);
StringPtr operator+(const StringPtr& lhs, const StringPtr& rhs);

// Comparison operators use an ordinal comparison

bool operator==(const UnicodeString& lhs, const UnicodeString& rhs);
bool operator==(const StringPtr& lhs, const StringPtr& rhs);

bool operator!=(const UnicodeString& lhs, const UnicodeString& rhs);
bool operator!=(const StringPtr& lhs, const StringPtr& rhs);

StringPtr ToString(double num); // TODO: i18n - number format options, locale
StringPtr ToString(unsigned long num); // TODO: 18n - number format options, locale

}

#endif

/*
 Copyright 2011 Greg Najda

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
